#include "gd32f4xx.h"
#include "sys_type.h"
#include "bsp_spi.h"
#include "bsp_timer.h"

void vBSP_SpiInit(void)
{
	spi_parameter_struct spi_init_struct;

	rcu_periph_clock_enable(RCU_GPIOA);
    gpio_af_set(GPIOA, GPIO_AF_5, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);

	nvic_irq_enable(SPI0_IRQn, 0, 0);

	rcu_periph_clock_enable(RCU_SPI0);
    spi_init_struct.trans_mode           = SPI_TRANSMODE_FULLDUPLEX;
    spi_init_struct.device_mode = SPI_SLAVE;
    spi_init_struct.frame_size           = SPI_FRAMESIZE_8BIT;
    spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE;
    spi_init_struct.nss         = SPI_NSS_HARD;
    spi_init_struct.prescale             = SPI_PSC_16;
    spi_init_struct.endian               = SPI_ENDIAN_MSB;
    spi_init(SPI0, &spi_init_struct);
    
    spi_i2s_interrupt_enable(SPI0, SPI_I2S_INT_RBNE);
    spi_enable(SPI0);


    return;

	

    rcu_periph_clock_enable(RCU_GPIOB);
	/* configure SPI1 GPIO */
	gpio_af_set(GPIOB, GPIO_AF_5, GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14|GPIO_PIN_15); 

	gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_13 | GPIO_PIN_14|GPIO_PIN_15);
	gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_13 | GPIO_PIN_14|GPIO_PIN_15);

	/* set SPI1_NSS as GPIO*/
	gpio_mode_set(GPIOB, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_12);
	gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_12);


	rcu_periph_clock_enable(RCU_SPI1);
	/* configure SPI1 parameter */
	spi_init_struct.trans_mode			 = SPI_TRANSMODE_FULLDUPLEX;
	spi_init_struct.device_mode 		 = SPI_MASTER;
	spi_init_struct.frame_size			 = SPI_FRAMESIZE_8BIT;
	spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_2EDGE;
	spi_init_struct.nss 				 = SPI_NSS_SOFT;
	spi_init_struct.prescale			 = SPI_PSC_2;
	spi_init_struct.endian				 = SPI_ENDIAN_MSB;
	spi_init(SPI1, &spi_init_struct);
}


SPI_STATUS ucBSP_SpiTransmitReceive(uint32_t SPIx, UCHAR *pTxData, UCHAR *pRxData, USHORT Size, ULONG Timeout)
{
    SPI_STATUS ucRet = SPI_OK;
	USHORT wk_idx = 0;
	ULONG tickstart = 0U;
	UCHAR txallowed = TRUE;
	
	if ((pTxData == NULL) || (pRxData == NULL) ||(Size == 0))
	{
		return SPI_ERROR;
	}

	if(spi_i2s_flag_get(SPIx,SPI_FLAG_TBE) ==RESET)
	{
		return SPI_BUSY;
	}
	
	/* Init tickstart for timeout management*/
	tickstart = HAL_GetTick();

	while(wk_idx < Size)
	{
		/* check TXE flag */
		if(txallowed && (spi_i2s_flag_get(SPIx,SPI_FLAG_TBE) !=RESET))
		{
			spi_i2s_data_transmit(SPIx,*(pTxData + wk_idx));
			/* Next Data is a reception (Rx). Tx not allowed */
			txallowed = FALSE;
		}

		/*wait rx */
		if(spi_i2s_flag_get(SPIx,SPI_FLAG_RBNE) !=RESET)
		{
			*(pRxData + wk_idx) = spi_i2s_data_receive(SPIx);
			wk_idx++;
			/* Next Data is a Transmission (Tx). Tx is allowed */
			txallowed = TRUE;
		}
		
		if ((Timeout != 0xFFFFFFFFU) && ((HAL_GetTick() - tickstart) >=  Timeout))
		{
			ucRet = SPI_TIMEOUT;
			break;
		}
	}

    return ucRet;
}


UCHAR u8_gSpiRevDataBuffer[100];
USHORT u9_gSpiRevLen = 0;
void SPI_RxCallBack(void)
{
	if(u9_gSpiRevLen < 100)
	{
		u8_gSpiRevDataBuffer[u9_gSpiRevLen++] = spi_i2s_data_receive(SPI0);
		spi_i2s_data_transmit(SPI0,0x33);
	}
}

